﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.Windows.Forms;
using System.Web;

using WebCrawlerTools.page;
using WebCrawlerTools.web;
using WebCrawlerTools.search;
using WebCrawlerTools.data;
using WebCrawlerTools.control;
using System.Text.RegularExpressions;
using WebCrawlerTools.form;

namespace WebCrawlerTools
{
    public class PageEventArgs : EventArgs
    {
        private Page page;

        public Page Page
        {
            get
            {
                return page;
            }
            set
            {
                page = value;
            }
        }
        public PageEventArgs(Page page)
        {
            this.page = page;
        }
    }
    public delegate void PageEventHandler(object sender, PageEventArgs e);
    public class PageDataEventArgs : EventArgs
    {
        private SResult result;

        public SResult Result
        {
            get
            {
                return result;
            }
            set
            {
                result = value;
            }
        }
        public PageDataEventArgs(SResult result)
        {
            this.result = result;
        }
    }
    public delegate void PageDataEventHandler(object sender, PageDataEventArgs e);

    public class SEngine
    {
        private ControlCenter controlCenter;

        public ControlCenter ControlCenter
        {
            get
            {
                return controlCenter;
            }
            set
            {
                controlCenter = value;
            }
        }

        private PHomePage homePage;

        public PHomePage HomePage
        {
            get
            {
                return homePage;
            }
            set
            {
                homePage = value;
            }
        }

        private SResult listPageData;
        public SResult ListPageData
        {
            get
            {
                return listPageData;
            }
            set
            {
                listPageData = value;
            }
        }

        private SResult detailPageData;
        public SResult DetailPageData
        {
            get
            {
                return detailPageData;
            }
            set
            {
                detailPageData = value;
            }
        }

        private string source;
        public String Source
        {
            get { return source; }
            set { source = value; }
        }
        private INet net;
        public INet Net
        {
            get
            {
                return net;
            }
        }
        private PageStatus Status;
        private int detailPageIndex;
        private SResult detailPageTotal;
        //-------------------------------------------------------------------------------------
        //Page Load Completed
        public event EventHandler OnePageLoadCompleted;
        //search page input complate page
        public event EventHandler SearchPageInputed;
        //search page  , search complete page
        public event EventHandler SearchPageSearched;
        //List page , display compete page
        public event EventHandler ListPageLoadCompleted;
        //List page  data analysisi complete page
        public event EventHandler ListPageAnalysisCompleted;
        //Detail page  , all page complete
        public event EventHandler ListPageAllCompleted;
        //Detail page  , display complete
        public event EventHandler DetailPageLoadCompleted;
        //List page  , data analysis complete
        public event EventHandler DetailPageAnalysisCompleted;
        //List page , detail page to list page
        public event EventHandler GoBackToListPageCompleted;
        //Detail Page , all page complete 
        public event EventHandler DetailPageAllCompleted;
        //next list page , display comleted
        public event EventHandler NextListPageLoadCompleted;
        //all event complete
        public event EventHandler AllPageCompleted;
        //UI page update page
        public event PageEventHandler UIUpdate;
        //UI data update page
        public event PageDataEventHandler UIDataUpdate;
        //-------------------------------------------------------------------------------------

        public SEngine()
        {
            net = new WebEngine();
            //pageEngine = new PageEngine();
            Net.WebLoaded += new EventHandler(this.OnWebPageOpened);
            detailPageIndex = 0;
            detailPageTotal = new SResult();
        }

        //Clear event
        public void EventReset()
        {
            OnePageLoadCompleted = null;
            SearchPageInputed = null;
            SearchPageSearched = null;
            ListPageLoadCompleted = null;
            ListPageAnalysisCompleted = null;
            ListPageAllCompleted = null;
            DetailPageLoadCompleted = null;
            DetailPageAnalysisCompleted = null;
            GoBackToListPageCompleted = null;
            DetailPageAllCompleted = null;
            NextListPageLoadCompleted = null;
        }
        //open apage
        public void OnWebPageOpened(object sender, EventArgs e)
        {
            source = Net.HtmlSrc();
            if (null != OnePageLoadCompleted)
            {
                OnePageLoadCompleted.Invoke(this, new EventArgs());
            }
        }

        //page display complete
        public void OnOnePageCompleted()
        {
            //display list page
            if (Status == PageStatus.SEARCH_END)
            {
                if (null != ListPageLoadCompleted)
                {
                    ListPageLoadCompleted.Invoke(this, new EventArgs());
                }
            }
            //display detail page
            else if(Status == PageStatus.OPEN_DETAIL_PAGE)
            {
                //TEST
                if (dataCenter.BasicInfo.DebugFlg)
                {
                    Log.Inst().Write(Net.HtmlSrc(),String.Format("{0:dd日hhmmssff}.html", DateTime.Now));
                }
                //detail page update
                if (null != UIUpdate)
                {
                    UIUpdate.Invoke(this, new PageEventArgs(homePage.DetailPage));
                }
                if (null != DetailPageLoadCompleted)
                {
                    DetailPageLoadCompleted.Invoke(this, new EventArgs());
                }
            }
            //after detail page go to list page, list page display
            else if (Status == PageStatus.BACK_TO_DETAIL)
            {
                //list page ui display
                if (null != UIUpdate)
                {
                    UIUpdate.Invoke(this, new PageEventArgs(homePage.ListPage));
                }
                //list page's ui data update
                if (null != UIDataUpdate)
                {
                    UIDataUpdate.Invoke(this, new PageDataEventArgs(listPageData));
                }
                //
                if (null != GoBackToListPageCompleted)
                {
                    GoBackToListPageCompleted.Invoke(this, new EventArgs());
                }
            }
            //display next list page 
            else if (Status == PageStatus.GOTO_NEXT_LIST_PAGE)
            {
                //list page ui update
                if (null != UIUpdate)
                {
                    UIUpdate.Invoke(this, new PageEventArgs(homePage.ListPage));
                }
                if (null != NextListPageLoadCompleted)
                {
                    NextListPageLoadCompleted.Invoke(this, new EventArgs());
                }
            }
            else if (Status == PageStatus.BACK_TO_SEARCH_PAGE)
            {
                if (null != AllPageCompleted)
                {
                    AllPageCompleted.Invoke(this, new EventArgs());
                }
            }
        }

        //search page - input 
        internal void SearchPageInput()
        {
            homePage.SearchPage.Input(WebEngine.Web.Document.Forms);
            if (null != SearchPageInputed)
            {
                SearchPageInputed.Invoke(this, new EventArgs());
            }
        }
        //search page - excute page
        internal void SearchPageStartSearch()
        {
            SResult sr = getData(source, homePage.SearchPage.Move.Template);
            //output Log
            Log.Inst().Write(sr.ToString());
            if (sr != null && sr.Data != null && sr.Data.Count > 0)
            {
                Js js = new Js();
                SLine sl = (SLine)sr.Data[0];
                js.Method = (String)sl.Data[0];
                for (int i = 1; i < sl.Data.Count; i++)
                {
                    js.Parameters.Add((string)sl.Data[i]);
                }
                Net.ExcuteJs(js);
                Status = PageStatus.SEARCH_END;
            }
            if (null != SearchPageSearched)
            {
                SearchPageSearched.Invoke(this, new EventArgs());
            }
        }
        //list page - data analysis
        internal void ListPageAnalysis()
        {
            //******************** Just for get Chatter User ********************
            ListPageData = SRDomParse.GetPersonList();

            //ListPageData = getData(source, homePage.ListPage.Template);
            //output Log
            Log.Inst().Write(ListPageData.ToString());
            //analysis complete
            if (null != ListPageAnalysisCompleted)
            {
                ListPageAnalysisCompleted.Invoke(this, new EventArgs());
            }
            //list page ui data update
            if (null != UIDataUpdate)
            {
                UIDataUpdate.Invoke(this, new PageDataEventArgs(listPageData));
            }
            //if none data,all list page will complete
            if (ListPageData == null || ListPageData.Data.Count == 0)
            {
                if (null != ListPageAllCompleted)
                {
                    ListPageAllCompleted.Invoke(this, new EventArgs());
                }
            }
        }

        //detail page - moving
        internal void OpenDetailPage()
        {
            if (ListPageData != null)
            {
                if (ListPageData.Data.Count > detailPageIndex)
                {
                    Js js = new Js();
                    SLine sl = (SLine)ListPageData.Data[detailPageIndex];
                    js.Method = (String)sl.Data[0];
                    for (int i = 1; i < sl.Data.Count; i++)
                    {
                        js.Parameters.Add((string)sl.Data[i]);
                    }
                    detailPageIndex++;
                    Net.ExcuteJs(js);
                    Status = PageStatus.OPEN_DETAIL_PAGE;
                }
                else
                {
                    //detail page comlete
                    detailPageIndex = 0;
                    if (null != DetailPageAllCompleted)
                    {
                        DetailPageAllCompleted.Invoke(this, new EventArgs());
                    }
                }
            }
        }
        //detail page -  data analysis
        internal void DetailPageAnalysis()
        {
            DetailPageData = getData(source, homePage.DetailPage.Template.Replace("\n", "\r\n"));
            //analysis complete
            //save data
            if (DetailPageData.Data.Count > 0)
            {
                detailPageTotal.Add(DetailPageData);
                //dataCenter.SaveDetailPageData(DetailPageData);
            }
            //output Log
            Log.Inst().Write(DetailPageData.ToString());
            //detail ui data update
            if (null != UIDataUpdate)
            {
                UIDataUpdate.Invoke(this, new PageDataEventArgs(detailPageData));
            }

            if (null != DetailPageAnalysisCompleted)
            {
                DetailPageAnalysisCompleted.Invoke(this, new EventArgs());
            }
        }
        //go back to list page 
        internal void GoBackToListPage()
        {
            SResult goback = getData(source, homePage.DetailPage.Move.Template);
            if(goback.Data.Count > 0)
            {
                Js js = new Js();
                SLine sl = (SLine)goback.Data[0];
                js.Method = (String)sl.Data[0];
                for (int i = 1; i < sl.Data.Count; i++)
                {
                    js.Parameters.Add((string)sl.Data[i]);
                }
                Net.ExcuteJs(js);
                Status = PageStatus.BACK_TO_DETAIL;
            }
        }
        //move to next detail page 
        internal void GoToNextDetailPage()
        {
            OpenDetailPage();
        }
        //list page, goto next page
        internal void GoToNextListPage()
        {
            //******************** Just for get Chatter User ********************
            GoToNextListPageForChatter();
            return;
            SResult gonext = getData(source, homePage.ListPage.Move.Template);
            if (gonext.Data.Count > 0)
            {
                Js js = new Js();
                SLine sl = (SLine)gonext.Data[0];
                js.Method = (String)sl.Data[0];
                for (int i = 1; i < sl.Data.Count; i++)
                {
                    string title = (string)gonext.Title.Data[i];
                    string data = (string)sl.Data[i];
                    if (title.StartsWith(SNode.JS_VAR_TAG))
                    {
                        string[] temp = data.Split('.');
                        if (temp.Length > 1)
                        {
                            string elementName = temp[temp.Length - 1];
                            string formName = temp[temp.Length - 2];
                            HtmlElement hdata = HElementFactory.getFormElement(WebEngine.Web.Document, formName, elementName);
                            js.Parameters.Add(hdata.DomElement);
                        }
                    }
                    else
                    {
                        js.Parameters.Add(data);
                    }
                }
                Net.ExcuteJs(js);
                Status = PageStatus.GOTO_NEXT_LIST_PAGE;
            }
            else
            {
                if (null != ListPageAllCompleted)
                {
                    ListPageAllCompleted.Invoke(this, new EventArgs());
                }
            }
        }
        //list page, goto next page
        //******************** Just for get Chatter User ********************
        internal void GoToNextListPageForChatter()
        {
            //<a href="javascript:Paginator.instances['000000000000000_paginator'].goToPage(2)">Next<img src="/s.gif" title="Next" alt="Next" class="next"></a>
            HtmlElement next_page_link = SRDomParse.GetNextPageLink();
            if (next_page_link != null)
            {
                next_page_link.InvokeMember("Click");
                Status = PageStatus.GOTO_NEXT_LIST_PAGE;
            }
            else
            {
                if (null != ListPageAllCompleted)
                {
                    ListPageAllCompleted.Invoke(this, new EventArgs());
                }
            }


        }
        //go back search page
        internal void GoBackToSearchPage()
        {
            //save data
            if (detailPageTotal.Data.Count > 0)
            {
                dataCenter.SaveDetailPageData(detailPageTotal);
                detailPageTotal.Data.Clear();
            }
            //save data
            SResult goback = getData(source, homePage.SearchPage.Template);
            if (goback.Data.Count > 0)
            {
                Js js = new Js();
                SLine sl = (SLine)goback.Data[0];
                js.Method = (String)sl.Data[0];
                for (int i = 1; i < sl.Data.Count; i++)
                {
                    js.Parameters.Add((string)sl.Data[i]);
                }
                Net.ExcuteJs(js);
                Status = PageStatus.BACK_TO_SEARCH_PAGE;
            }
        }
        //-------------------------------------------------------------------------------------
        //get data
        public static SResult getData(string source, string template)
        {
            PageEngine pe = new PageEngine();
            pe.Source = source;
            pe.Template = new STemplate(template);
            pe.analysis();
            return pe.Result;
        }

        //-------------------------------------------------------------------------------------
        //private PageEngine pageEngine;
        private DataCenter dataCenter;

        //private ArrayList detailPageUriList;
        //private Page page = null;
        //private STemplate template;

        //public bool GoNextPage()
        //{
        //    string url = getNextPageUrl();
        //    if (!String.IsNullOrEmpty(url))
        //    {
        //        net.OpenUri(url);
        //        return true;
        //    }
        //    return false;
        //}

        //public string getNextPageUrl()
        //{
        //    string newurl = "";
        //    if (!String.IsNullOrEmpty(page.Move.Template))
        //    {
        //        pageEngine.Source = source;
        //        pageEngine.Template = new STemplate(page.Move.Template);
        //        pageEngine.analysis();
        //        if (pageEngine.Result.Data.Count > 0)
        //        {
        //            if (page.Move.Type == LoopType.URL)
        //            {
        //                SLine line = (SLine)pageEngine.Result.Data[0];
        //                newurl = getAbsoluteUrl((String)line.Data[0]);
        //            }
        //        }
        //    }
        //    return newurl;
        //}

        //private string getAbsoluteUrl(String url)
        //{
        //    url = HttpUtility.HtmlDecode(url);
        //    if (!url.StartsWith("http://"))
        //    {
        //        if (url.StartsWith("/"))
        //        {
        //            url = "http://" + net.Uri.Host + url;
        //        }
        //        else
        //        {
        //            string oldurl = net.Uri.AbsoluteUri;
        //            url = oldurl.Substring(0, oldurl.LastIndexOf("/") + 1) + url;
        //        }
        //    }
        //    return url;
        //}

        //public bool GoNextSubPage()
        //{
        //    if (null != detailPageUriList)
        //    {
        //        if (detailPageIndex < detailPageUriList.Count)
        //        {
        //            String url = (String)detailPageUriList[detailPageIndex++];
        //            net.OpenUri(getAbsoluteUrl(url));
        //            return true;
        //        }
        //    }
        //    return false;
        //}

        //public void StartDetailPage(object sender, EventArgs e)
        //{
        //    if (null != page)
        //    {
        //        detailPageUriList = dataCenter.DataInfo.GetDetailPageUrlList();
        //        template = new STemplate(page.Template.Replace("\n", "\r\n"));
        //        detailPageIndex = 0;
        //        if (null != detailPageUriList && detailPageUriList.Count > detailPageIndex)
        //        {
        //            String url = (String)detailPageUriList[detailPageIndex++];
        //            net.OpenUri(getAbsoluteUrl(url));
        //        }
        //    }
        //}

        public WebCrawlerTools.data.DataCenter DataCenter
        {
            get
            {
                return dataCenter;
            }
            set
            {
                dataCenter = value;
            }
        }

        //internal WebCrawlerTools.search.PageEngine PageEngine
        //{
        //    get
        //    {
        //        return pageEngine;
        //    }
        //}

    }
}
